package logic

import (
	"bytes"

	"../utils"
)

type LRUIndex struct {
	unix     uint64
	position uint
}

type LRU struct {
	Count  uint
	Total  uint
	cache  map[uint64][]*Session
	record map[string]*LRUIndex
}

func InitLRUCache() *LRU {
	return &LRU{
		Count:  0,
		cache:  make(map[uint64][]*Session),
		record: make(map[string]*LRUIndex),
	}
}

func BuildKey(id, ns string) string {
	var buffer bytes.Buffer
	buffer.WriteString(id)
	buffer.WriteByte(0x2d)
	buffer.WriteString(ns)
	return buffer.String()
}

func (lru *LRU) find(id, ns string) (bool, *Session) {
	key := BuildKey(id, ns)
	index, ok := lru.record[key]
	if !ok {
		return false, nil
	}

	if cache, ok := lru.cache[index.unix]; ok {
		if uint(len(cache)) > index.position {
			session := cache[index.position]
			lru.remove(key, index)

			return true, session
		}
	}

	return false, nil
}

func (lru *LRU) remove(key string, index *LRUIndex) {
	unix := index.unix
	i := index.position
	if uint(len(lru.cache[unix])) > i+1 {
		lru.cache[unix] = append(lru.cache[unix][:i], lru.cache[unix][i:]...)
	} else {
		lru.cache[unix] = lru.cache[unix][:i]
	}

	delete(lru.record, key)
}

func (lru *LRU) release() {

}

func (lru *LRU) Cache(session *Session) *LRUIndex {
	key := BuildKey(session.GetId(), session.Ns)

	unix := uint64(utils.Nowtime() / 30 * 30)
	if _, ok := lru.cache[unix]; !ok {
		lru.cache[unix] = make([]*Session, 0)
		lru.Count += 1
	}

	lru.cache[unix] = append(lru.cache[unix], session)
	lru.record[key] = &LRUIndex{
		unix:     unix,
		position: uint(len(lru.cache[unix]) - 1),
	}
	lru.Total += 1

	return nil
}
